package com.why.generate;

import com.why.config.GeneratorConfig;
import com.why.model.MsgModel;
import com.why.model.RequestModel;
import com.why.model.TemplateGenModel;
import com.why.util.FreeMarkerTemplateUtils;
import freemarker.template.Template;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class QueryRequestGenerator implements BaseGenerator {
    private static final String templateName = "QueryRequest.ftl";

    @Override
    public void generate(GeneratorConfig config, MsgModel msgModel) {
        try {
            RequestModel requestModel = getRequestModel(config, msgModel);
            TemplateGenModel templateGenModel = assembleTemplateGenModel(config, requestModel, msgModel);
            Template template = FreeMarkerTemplateUtils.getTemplate(templateGenModel.getTemplateName());
            FileOutputStream fos = new FileOutputStream(templateGenModel.getMapperFile());
            Writer out = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8), 10240);
            template.process(templateGenModel.getDataMap(), out);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static TemplateGenModel assembleTemplateGenModel(GeneratorConfig config, RequestModel requestModel, MsgModel msgModel) throws IOException {
        // 1. 创建文件的绝对路径，并创建文件
        File pageFile = new File(config.getBasePackage());
        if (!pageFile.exists()) {
            pageFile.mkdirs();
        }
        String path = config.getBasePath() + File.separator + requestModel.getMsgName() + ".java";
        File mapperFile = new File(path);
        if (!mapperFile.exists()) {
            mapperFile.createNewFile();
        }
        // 2. 模板中需要的参数信息
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.putIfAbsent("basePackage", config.getBasePackage());
        dataMap.putIfAbsent("msgName", requestModel.getMsgName());
        dataMap.putIfAbsent("msgDesc", requestModel.getMsgDesc());
        dataMap.putIfAbsent("author", config.getAuthor());
        dataMap.putIfAbsent("param_combine_list", requestModel.getParamModelList());
        dataMap.putIfAbsent("combine_list", msgModel.getCombineParam());
        assembleChildClass(dataMap, msgModel);
        return new TemplateGenModel(templateName, mapperFile, dataMap);
    }

    private static RequestModel getRequestModel(GeneratorConfig config, MsgModel msgModel) {
        RequestModel requestModel = new RequestModel();
        requestModel.setMsgName(msgModel.getMsgName());
        requestModel.setMsgDesc(msgModel.getMsgDesc());
        List<String> baseQueryParamList = config.getRequestConfig().getBaseQueryParamList();
        msgModel.getCombineParam().forEach(model -> {
            if (baseQueryParamList.contains(model.getParamName())) {
                return;
            }
            RequestModel.ParamModel paramModel = new RequestModel.ParamModel();
            paramModel.setParamName(model.getOutParamName());
            paramModel.setParamDesc(model.getParamDesc());
            paramModel.setParamType(model.getOutParamType());
            paramModel.setDefaultValue(model.getDefaultValue());
            paramModel.setMsgParamType(model.getMsgParamType());
            paramModel.setParamCharType(model.getParamCharType());
            requestModel.getParamModelList().add(paramModel);
        });
        return requestModel;
    }

    /**
     * 获取内部类信息，由于现实情况，只考虑到两次内部类
     */
    private static void assembleChildClass(Map<String, Object> dataMap, MsgModel msgModel) {
        MsgModel childMsgModel = msgModel.getChildModel();
        if (childMsgModel != null) {
            Map<String, Object> InnerClassDataMap = new HashMap<>();
            InnerClassDataMap.putIfAbsent("msgName", childMsgModel.getMsgName());
            InnerClassDataMap.putIfAbsent("msgDesc", childMsgModel.getMsgDesc());
            InnerClassDataMap.putIfAbsent("param_combine_list", childMsgModel.getCombineParam());

            if (childMsgModel.getChildModel() != null) {
                Map<String, Object> InnerInnerClassDataMap = new HashMap<>();
                InnerInnerClassDataMap.putIfAbsent("msgName", childMsgModel.getChildModel().getMsgName());
                InnerInnerClassDataMap.putIfAbsent("msgDesc", childMsgModel.getChildModel().getMsgDesc());
                InnerInnerClassDataMap.putIfAbsent("param_combine_list", childMsgModel.getChildModel().getCombineParam());
                InnerClassDataMap.put("inner_inner_class", InnerInnerClassDataMap);
            }
            dataMap.put("inner_class", InnerClassDataMap);
        }
    }
}
